home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 13547 / 13547.xpi / chrome / content / overlay.js < prev    next >
Text File  |  2009-12-02  |  47KB  |  1,699 lines

  1. //Licensed under GNU General Public License, version 3.0
  2. //Copyright Damien Brunet
  3. //I'm working on a Google Chrome port (actually several ports... aFCA has too many features)
  4.  
  5. var aFCA =
  6. {
  7.     getSelectedText: function ()
  8.     {
  9.         var selection = document.commandDispatcher.focusedWindow.getSelection();
  10.         
  11.         if (selection)
  12.         {
  13.             var text = aFCA.trim(selection.toString());
  14.         }
  15.         else
  16.         {
  17.             var text = "";
  18.         }
  19.         
  20.         return text;
  21.     },
  22.     
  23.     
  24.     getSelectedTextWithin: function ()
  25.     {
  26.         var popupNode = document.popupNode;
  27.         
  28.         
  29.         if (popupNode && ((popupNode.localName.toLowerCase() == "input" && popupNode.type == "text") || popupNode.localName.toLowerCase() == "textarea"))
  30.         {
  31.             var text = aFCA.trim(popupNode.value.substring(popupNode.selectionStart, popupNode.selectionEnd));
  32.         }
  33.         else
  34.         {
  35.             var text = "";
  36.         }
  37.  
  38.         return text;
  39.     },
  40.     
  41.     
  42.     trim: function (text)
  43.     {
  44.         return text.replace(/^\s+/, "").replace(/\s+$/, "").replace(/\s+/g, " ");
  45.     },
  46.     
  47.     
  48.     getUrl: function (item, from)
  49.     {
  50.         var text = encodeURIComponent(aFCA.lastSelection);
  51.  
  52.         switch (item)
  53.         {
  54.             case "googleTranslate":
  55.             {
  56.                 if (from == "input")
  57.                 {
  58.                     var srcLang = aFCA.p.quickW.srcLang;
  59.                     var destLang = aFCA.p.quickW.destLang;
  60.                 }
  61.                 else
  62.                 {
  63.                     var srcLang = aFCA.p.quick.srcLang;
  64.                     var destLang = aFCA.p.quick.destLang;
  65.                 }
  66.                 
  67.                 return "http://translate.google.com/#" + srcLang + "|" + destLang + "|" + text;
  68.             }
  69.             case "googleDictionary":
  70.             {
  71.                 if (aFCA.p.googleDictionary.mono && aFCA.p.googleDictionary.lang == "auto|auto")
  72.                 {
  73.                     aFCA.detectLanguage(text, function (lang)
  74.                         {
  75.                             var lang = lang + "|" + lang;
  76.                             
  77.                             if (!aFCA.isInMonolingualDictionary(lang))
  78.                             {
  79.                                 lang = "en|en";
  80.                             }
  81.                             
  82.                             var url = "http://www.google.com/dictionary?langpair=" + lang + "&q=" + text;
  83.                             
  84.                             aFCA.openItem(url);
  85.                         }
  86.                     )
  87.                     
  88.                     return;
  89.                 }
  90.                 else if (aFCA.p.googleDictionary.bi && aFCA.p.googleDictionary.langpair == "auto|en")
  91.                 {
  92.                     aFCA.detectLanguage(text, function (lang)
  93.                         {
  94.                             var langpair = lang + "|" + "en";
  95.                             
  96.                             if (!aFCA.isInBilingualDictionary(langpair))
  97.                             {
  98.                                 langpair = "en|en";
  99.                             }
  100.                             
  101.                             var url = "http://www.google.com/dictionary?langpair=" + langpair + "&q=" + text;
  102.                             
  103.                             aFCA.openItem(url);
  104.                         }
  105.                     )
  106.                     
  107.                     return;
  108.                 }
  109.                 else if (aFCA.p.googleDictionary.bi)
  110.                 {
  111.                     return "http://www.google.com/dictionary?langpair=" + aFCA.p.googleDictionary.langpair + "&q=" + text;
  112.                 }
  113.                 else
  114.                 {
  115.                     return "http://www.google.com/dictionary?langpair=" + aFCA.p.googleDictionary.lang + "&q=" + text;
  116.                 }
  117.             }
  118.             case "customItem1":
  119.             {
  120.                 return aFCA.p.customItem1.url.replace(/%s/g, text);
  121.             }
  122.             case "customItem2":
  123.             {
  124.                 return aFCA.p.customItem2.url.replace(/%s/g, text);
  125.             }
  126.             case "customItem3":
  127.             {
  128.                 return aFCA.p.customItem3.url.replace(/%s/g, text);
  129.             }
  130.             case "newChildTab":
  131.             {
  132.                 return gContextMenu.linkURL;
  133.             }
  134.             case "translateThisPage":
  135.             {
  136.                 return "http://translate.google.com/translate?sl=auto&tl=" + aFCA.p.translateThisPage.destLang + "&u=" + aFCA.getCurrentUrl();
  137.             }
  138.             default:
  139.             {
  140.                 return item;
  141.             }
  142.         }
  143.     },
  144.     
  145.     
  146.     isInMonolingualDictionary: function (lang)
  147.     {
  148.         var list = ["zh-CN|zh-CN", "zh-TW|zh-TW", "cs|cs", "nl|nl", "en|en", "fr|fr", "de|de", "it|it", "ko|ko", "pt|pt", "ru|ru", "es|es"];
  149.         
  150.         for (var i = 0; i < list.length; i++)
  151.         {
  152.             if (list[i] == lang)
  153.             {
  154.                 return true;
  155.             }
  156.         }
  157.         
  158.         return false;
  159.     },
  160.     
  161.     
  162.     isInBilingualDictionary: function (langpair)
  163.     {
  164.         var list = ["ar|en", "bn|en", "bg|en", "zh-CN|en", "zh-TW|en", "hr|en", "cs|en", "fi|en", "fr|en", "de|en", "el|en", "gu|en", "iw|en", "hi|en", "it|en", "kn|en", "ko|en", "ml|en", "mr|en", "pt|en", "ru|en", "sr|en", "es|en", "ta|en", "te|en", "th|en"];
  165.         
  166.         for (var i = 0; i < list.length; i++)
  167.         {
  168.             if (list[i] == langpair)
  169.             {
  170.                 return true;
  171.             }
  172.         }
  173.         
  174.         return false;
  175.     },
  176.     
  177.     
  178.     openItem: function (item, from)
  179.     {
  180.         var url = aFCA.getUrl(item, from);
  181.         
  182.         if (!url)
  183.         {
  184.             return;
  185.         }
  186.         
  187.         var parentTab = gBrowser.selectedTab;
  188.         var childTab = gBrowser.addTab(url);
  189.         
  190.         if (aFCA.p.stuff.here && from != "input")
  191.         {
  192.             aFCA.hideBubble();
  193.             
  194.             if (aFCA.p.stuff.unselect)
  195.             {
  196.                 goDoCommand('cmd_selectNone');
  197.             }
  198.  
  199.             if (item == "customItem1" || item == "customItem2" || item == "customItem3" || item == "googleDictionary" || item == "googleTranslate" || item.match("q="))
  200.             {
  201.                 aFCA.updateHereDisplay(aFCA.lastSelectionEvent);
  202.             }
  203.             else if (item == "newChildTab")
  204.             {
  205.                 aFCA.updateHereDisplay(aFCA.lastRightClick);
  206.             }
  207.         }
  208.         
  209.         gBrowser.selectedTab = childTab;
  210.         
  211.         if (aFCA.p.stuff.bool)
  212.         {
  213.             aFCA.tagTabs(childTab, parentTab);
  214.         }
  215.     },
  216.     
  217.     
  218.     tagTabs: function (childTab, parentTab)
  219.     {
  220.         var parentTabID = aFCA.ss.getTabValue(parentTab, "ID");
  221.         
  222.         if (!parentTabID)
  223.         {
  224.             var parentTabID = Math.floor(Math.random()*10000);
  225.             aFCA.ss.setTabValue(parentTab, "ID", parentTabID);
  226.         }
  227.         
  228.         aFCA.ss.setTabValue(childTab, "parentTabID", parentTabID);
  229.     },
  230.     
  231.     
  232.     init: function ()
  233.     {
  234.         aFCA.translated = true;
  235.         
  236.         aFCA.ss = Components.classes["@mozilla.org/browser/sessionstore;1"]
  237.                             .getService(Components.interfaces.nsISessionStore);
  238.  
  239.         aFCA.pf = Components.classes["@mozilla.org/preferences-service;1"]
  240.                             .getService(Components.interfaces.nsIPrefService)
  241.  
  242.         aFCA.prefsAfca = aFCA.pf.getBranch("extensions.aFCA.");
  243.         aFCA.prefsGeneral = aFCA.pf.getBranch("general.");
  244.         
  245.         aFCA.getPrefs();
  246.         
  247.         aFCA.prefsAfca.QueryInterface(Components.interfaces.nsIPrefBranch2);
  248.         aFCA.prefsAfca.addObserver("", this, false);
  249.         
  250.         if (aFCA.p.stuff.middleClick)
  251.         {
  252.             aFCA.prefsGeneral.setBoolPref("autoScroll", false);
  253.         }
  254.         
  255.         if (aFCA.p.autoConfig)
  256.         {
  257.             aFCA.autoConfig();
  258.         }
  259.         
  260.         function onTabSelect (e)
  261.         {
  262.             aFCA.hideSkin();
  263.         }
  264.         gBrowser.tabContainer.addEventListener("TabSelect", function (e) {onTabSelect(e);}, false);
  265.  
  266.         function onPageLoad (e)
  267.         {
  268.             var doc = e.originalTarget;
  269.             var indexTab = gBrowser.getBrowserIndexForDocument(doc);
  270.             
  271.             if (indexTab == -1 || !doc.body)
  272.             {
  273.                 return;
  274.             }
  275.         
  276.             if (aFCA.ss.getTabValue(gBrowser.mTabs[indexTab], "parentTabID") && aFCA.p.stuff.middleClick)
  277.             {
  278.                 aFCA.initSkin(doc);
  279.             }
  280.         
  281.             if (aFCA.p.quick.bubble)
  282.             {
  283.                 aFCA.initBubble(doc);
  284.             }
  285.             
  286.             if (aFCA.p.stuff.here)
  287.             {
  288.                 aFCA.initHere(doc);
  289.             }
  290.         }
  291.         document.addEventListener("DOMContentLoaded", function (e) {onPageLoad(e);}, false);
  292.         
  293.         aFCA.getMenuItems();
  294.         
  295.         function onPopupShowing (e)
  296.         {
  297.             if (e.target.id != "contentAreaContextMenu")
  298.             {
  299.                 return;
  300.             }
  301.             
  302.             aFCA.drawMenu();
  303.         }
  304.         document.addEventListener("popupshowing", function (e) {onPopupShowing(e);}, false);
  305.     },
  306.     
  307.     
  308.     autoConfig: function ()
  309.     {
  310.         var locale = aFCA.p.locale;
  311.         var lang = locale.replace(/-.+/, "");
  312.         
  313.         if (lang == "he")
  314.         {
  315.             lang = "iw";
  316.         }
  317.         
  318.         if (aFCA.isSupportedByGoogleApi(locale))
  319.         {
  320.             aFCA.prefsAfca.setCharPref("quick.destLang", locale);
  321.             aFCA.prefsAfca.setCharPref("quickW.destLang", locale);
  322.             aFCA.prefsAfca.setCharPref("translateThisPage.destLang", locale);
  323.         }
  324.         else if (aFCA.isSupportedByGoogleApi(lang))
  325.         {
  326.             aFCA.prefsAfca.setCharPref("quick.destLang", lang);
  327.             aFCA.prefsAfca.setCharPref("quickW.destLang", lang);
  328.             aFCA.prefsAfca.setCharPref("translateThisPage.destLang", lang);
  329.         }
  330.         
  331.         if (aFCA.isInBilingualDictionary(locale + "|en"))
  332.         {
  333.             aFCA.prefsAfca.setCharPref("googleDictionary.langpair", "en|" + locale);
  334.         }
  335.         else if (aFCA.isInBilingualDictionary(lang + "|en"))
  336.         {
  337.             aFCA.prefsAfca.setCharPref("googleDictionary.langpair", "en|" + lang);
  338.         }
  339.         
  340.         aFCA.prefsAfca.setBoolPref("autoConfig", false);
  341.     },
  342.     
  343.     
  344.     isSupportedByGoogleApi: function (lang)
  345.     {
  346.         var list = ["af", "sq", "ar", "be", "bg", "ca", "zh-CN", "zh-TW", "hr", "cs", "da", "nl", "en", "et", "tl", "fi", "fr", "gl", "de", "el", "iw", "hi", "hu", "is", "id", "ga", "it", "ja", "ko", "lv", "lt", "mk", "ms", "mt", "no", "fa", "pl", "pt", "ro", "ru", "sr", "sk", "sl", "es", "sw", "sv", "th", "tr", "uk", "vi", "cy", "yi"];
  347.         
  348.         for (var i = 0; i < list.length; i++)
  349.         {
  350.             if (list[i] == lang)
  351.             {
  352.                 return true;
  353.             }
  354.         }
  355.         
  356.         return false;
  357.     },
  358.     
  359.     
  360.     closeAndGo: function (from)
  361.     {
  362.         var childTab = gBrowser.selectedTab;
  363.         var parentTabID = aFCA.ss.getTabValue(childTab, "parentTabID"); 
  364.         var tabCount = gBrowser.mPanelContainer.childNodes.length;
  365.         
  366.         for (var tab, found = false, i = 0; i < tabCount && !found; i++)
  367.         {
  368.             tab = gBrowser.mTabs[i];
  369.             
  370.             if (aFCA.ss.getTabValue(tab, "ID") == parentTabID)
  371.             {
  372.                 gBrowser.selectedTab = tab;
  373.                 found = true;
  374.             }
  375.         }
  376.         
  377.         if (aFCA.lastMouseMove && content.document.getElementById("skin") && from == "click")
  378.         {
  379.             aFCA.updateSkinDisplay(aFCA.lastMouseMove);
  380.         }
  381.         
  382.         if (!found)
  383.         {
  384.             gBrowser.removeTab(childTab);
  385.         }
  386.         else
  387.         {
  388.             setTimeout(function () {gBrowser.removeTab(childTab);}, 100); //In order to avoid the "flicker"
  389.         }
  390.     },
  391.     
  392.     
  393.     injectStretch: function (doc)
  394.     {
  395.         aFCA.injectStyle(doc, "html {width: 100%; height: 100%;}", "stretch");
  396.     },
  397.     
  398.     
  399.     restoreChildTab: function ()
  400.     {
  401.         var list = JSON.parse(aFCA.ss.getClosedTabData(window));
  402.         
  403.         var currentTab = gBrowser.selectedTab;
  404.         var currentTabID = aFCA.ss.getTabValue(currentTab, "ID");
  405.         
  406.         for (var i = 0; i < list.length; i++)
  407.         {
  408.             if (list[i].state.extData && list[i].state.extData.parentTabID && list[i].state.extData.parentTabID == currentTabID)
  409.             {
  410.                 aFCA.ss.undoCloseTab(window, i);
  411.                 break;
  412.             }
  413.         }
  414.     },
  415.     
  416.     //gTranslate
  417.     replaceSelection: function ()
  418.     {
  419.         var popupNode = document.popupNode;
  420.         var iStart = popupNode.selectionStart;
  421.         var iEnd = popupNode.selectionEnd;
  422.         var trans = aFCA.processText(aFCA.lastTranslation);
  423.         popupNode.value = popupNode.value.substring(0, iStart) + trans + popupNode.value.substring(iEnd, popupNode.value.length);
  424.         popupNode.setSelectionRange(iStart, iStart + trans.length); 
  425.     },
  426.     
  427.     
  428.     getCurrentUrl: function ()
  429.     {
  430.         return gBrowser.selectedBrowser.currentURI.spec;
  431.     },
  432.     
  433.     
  434.     getMenuItems: function ()
  435.     {
  436.         aFCA.menu_quick = document.getElementById("aFCA-menu-quick");
  437.         aFCA.item2_quick = document.getElementById("aFCA-item2-quick");
  438.         aFCA.translateFrom = document.getElementById("aFCA-translateFrom");
  439.         aFCA.translateTo = document.getElementById("aFCA-translateTo");
  440.         aFCA.item1_quick = document.getElementById("aFCA-item1-quick");
  441.         aFCA.sep_quick = document.getElementById("aFCA-sep-quick");
  442.         aFCA.item_googleDictionary = document.getElementById("aFCA-googleDictionary");
  443.         aFCA.item_customItem1 = document.getElementById("aFCA-customItem1");
  444.         aFCA.item_customItem2 = document.getElementById("aFCA-customItem2");
  445.         aFCA.item_customItem3 = document.getElementById("aFCA-customItem3");
  446.         aFCA.sep_searchItems = document.getElementById("aFCA-sep-searchItems");
  447.         aFCA.item_newChildTab = document.getElementById("aFCA-newChildTab");
  448.         aFCA.sep_newChildTab = document.getElementById("aFCA-sep-newChildTab");
  449.         aFCA.item_restoreChildTab = document.getElementById("aFCA-restoreChildTab");
  450.         aFCA.sep_restoreChildTab = document.getElementById("aFCA-sep-restoreChildTab");
  451.         aFCA.item_translateThisPage = document.getElementById("aFCA-translateThisPage");
  452.         aFCA.sep_translateThisPage = document.getElementById("aFCA-sep-translateThisPage");
  453.         aFCA.item_closeThisChildTab = document.getElementById("aFCA-closeThisChildTab");
  454.         aFCA.sep_closeThisChildTab = document.getElementById("aFCA-sep-closeThisChildTab");
  455.         aFCA.item_blacklist = document.getElementById("aFCA-blacklist");
  456.         aFCA.sep_blacklist = document.getElementById("aFCA-sep-blacklist");
  457.         
  458.         aFCA.stringsBundle = document.getElementById("aFCA-stringsBundle");
  459.  
  460.         aFCA.item_openlink = document.getElementById("context-openlink");
  461.         aFCA.item_bookmarklink = document.getElementById("context-bookmarklink");
  462.         aFCA.item_sendlink = document.getElementById("context-sendlink");
  463.         aFCA.item_sendimage = document.getElementById("context-sendimage");
  464.         aFCA.item_setDesktopBackground = document.getElementById("context-setDesktopBackground");
  465.         aFCA.item_blockimage = document.getElementById("context-blockimage");
  466.         aFCA.item_sendvideo = document.getElementById("context-sendvideo");
  467.         aFCA.item_sendaudio = document.getElementById("context-sendaudio");
  468.         aFCA.item_back = document.getElementById("context-back");
  469.         aFCA.item_forward = document.getElementById("context-forward");
  470.         aFCA.item_reload = document.getElementById("context-reload");
  471.         aFCA.item_stop = document.getElementById("context-stop");
  472.         aFCA.sep_stop = document.getElementById("context-sep-stop");
  473.         aFCA.item_bookmarkpage = document.getElementById("context-bookmarkpage");
  474.         aFCA.item_savepage = document.getElementById("context-savepage");
  475.         aFCA.item_sendpage = document.getElementById("context-sendpage");
  476.         aFCA.sep_viewbgimage = document.getElementById("context-sep-viewbgimage");
  477.         aFCA.item_viewbgimage = document.getElementById("context-viewbgimage");
  478.         aFCA.item_undo = document.getElementById("context-undo");
  479.         aFCA.sep_undo = document.getElementById("context-sep-undo");
  480.         aFCA.item_cut = document.getElementById("context-cut");
  481.         aFCA.item_copy = document.getElementById("context-copy");
  482.         aFCA.item_paste = document.getElementById("context-paste");
  483.         aFCA.item_delete = document.getElementById("context-delete");
  484.         aFCA.sep_paste = document.getElementById("context-sep-paste");
  485.         aFCA.item_selectall = document.getElementById("context-selectall");
  486.         aFCA.sep_selectall = document.getElementById("context-sep-selectall");
  487.         aFCA.item_keywordfield = document.getElementById("context-keywordfield");
  488.         aFCA.item_searchselect = document.getElementById("context-searchselect");
  489.         aFCA.sep_frame = document.getElementById("frame-sep");
  490.         aFCA.menu_frame = document.getElementById("frame");
  491.         aFCA.item_viewpartialsourceSelection = document.getElementById("context-viewpartialsource-selection");
  492.         aFCA.item_viewpartialsourceMathml = document.getElementById("context-viewpartialsource-mathml");
  493.         aFCA.sep_viewsource = document.getElementById("context-sep-viewsource");
  494.         aFCA.item_viewsource = document.getElementById("context-viewsource");
  495.         aFCA.item_viewinfo = document.getElementById("context-viewinfo");
  496.         aFCA.sep_spell = document.getElementById("spell-separator");
  497.         aFCA.item_spellCheck = document.getElementById("spell-check-enabled");
  498.         
  499.         aFCA.item_saveimage = document.getElementById("context-saveimage");
  500.         
  501.         //To-Remove after 3.6
  502.         aFCA.sep_properties = document.getElementById("context-sep-properties");
  503.         aFCA.item_metadata = document.getElementById("context-metadata");
  504.     },
  505.     
  506.     
  507.     drawMenu: function ()
  508.     {
  509.         var text = aFCA.getSelectedText();
  510.         var textWithin = aFCA.getSelectedTextWithin();
  511.         var doc = content.document;
  512.         
  513.         aFCA.menu_quick.hidden = true;
  514.         aFCA.item1_quick.hidden = true;
  515.         aFCA.sep_quick.hidden = true;
  516.         aFCA.item_googleDictionary.hidden = true;
  517.         aFCA.item_customItem1.hidden = true;
  518.         aFCA.item_customItem2.hidden = true;
  519.         aFCA.item_customItem3.hidden = true;
  520.         aFCA.sep_searchItems.hidden = true;
  521.         aFCA.item_newChildTab.hidden = true;
  522.         aFCA.sep_newChildTab.hidden = true;
  523.         aFCA.item_restoreChildTab.hidden = true;
  524.         aFCA.sep_restoreChildTab.hidden = true;
  525.         aFCA.item_translateThisPage.hidden = true;
  526.         aFCA.sep_translateThisPage.hidden = true;
  527.         aFCA.item_closeThisChildTab.hidden = true;
  528.         aFCA.sep_closeThisChildTab.hidden = true;
  529.         aFCA.item_blacklist.hidden = true;
  530.         aFCA.sep_blacklist.hidden = true;
  531.         
  532.         if (aFCA.p.pruning.openlink)
  533.         {
  534.             aFCA.item_openlink.hidden = true;
  535.         }
  536.         if (aFCA.p.pruning.bookmarklink)
  537.         {
  538.             aFCA.item_bookmarklink.hidden = true;
  539.         }
  540.         if (aFCA.p.pruning.sendlink)
  541.         {
  542.             aFCA.item_sendlink.hidden = true;
  543.         }
  544.         if (aFCA.p.pruning.sendimage)
  545.         {
  546.             aFCA.item_sendimage.hidden = true;
  547.         }
  548.         if (aFCA.p.pruning.setDesktopBackground)
  549.         {
  550.             aFCA.item_setDesktopBackground.hidden = true;
  551.         }
  552.         if (aFCA.p.pruning.blockimage)
  553.         {
  554.             aFCA.item_blockimage.hidden = true;
  555.         }
  556.         if (aFCA.p.pruning.sendvideo)
  557.         {
  558.             aFCA.item_sendvideo.hidden = true;
  559.         }
  560.         if (aFCA.p.pruning.sendaudio)
  561.         {
  562.             aFCA.item_sendaudio.hidden = true;
  563.         }
  564.         if (aFCA.p.pruning.back)
  565.         {
  566.             aFCA.item_back.hidden = true;
  567.         }
  568.         if (aFCA.p.pruning.forward)
  569.         {
  570.             aFCA.item_forward.hidden = true;
  571.         }
  572.         if (aFCA.p.pruning.reload)
  573.         {
  574.             aFCA.item_reload.hidden = true;
  575.         }
  576.         if (aFCA.p.pruning.stop)
  577.         {
  578.             aFCA.item_stop.hidden = true;
  579.         }
  580.         if (aFCA.p.pruning.stop && aFCA.p.pruning.reload && aFCA.p.pruning.forward && aFCA.p.pruning.back)
  581.         {
  582.             aFCA.sep_stop.hidden = true;
  583.         }
  584.         if (aFCA.p.pruning.bookmarkpage)
  585.         {
  586.             aFCA.item_bookmarkpage.hidden = true;
  587.         }
  588.         if (aFCA.p.pruning.savepage)
  589.         {
  590.             aFCA.item_savepage.hidden = true;
  591.         }
  592.         if (aFCA.p.pruning.sendpage)
  593.         {
  594.             aFCA.item_sendpage.hidden = true;
  595.         }
  596.         if (aFCA.p.pruning.viewbgimage)
  597.         {
  598.             aFCA.item_viewbgimage.hidden = true;
  599.             aFCA.sep_viewbgimage.hidden = true;
  600.         }
  601.         if (aFCA.p.pruning.undo)
  602.         {
  603.             aFCA.item_undo.hidden = true;
  604.             aFCA.sep_undo.hidden = true;
  605.         }
  606.         if (aFCA.p.pruning.cut)
  607.         {
  608.             aFCA.item_cut.hidden = true;
  609.         }
  610.         if (aFCA.p.pruning.copy)
  611.         {
  612.             aFCA.item_copy.hidden = true;
  613.         }
  614.         if (aFCA.p.pruning.paste)
  615.         {
  616.             aFCA.item_paste.hidden = true;
  617.         }
  618.         if (aFCA.p.pruning.del)
  619.         {
  620.             aFCA.item_delete.hidden = true;
  621.         }
  622.         if (aFCA.p.pruning.selectall)
  623.         {
  624.             aFCA.item_selectall.hidden = true;
  625.             aFCA.sep_selectall.hidden = true;
  626.         }
  627.         if ((aFCA.item_cut.hidden && aFCA.item_copy.hidden && aFCA.item_paste.hidden && aFCA.item_delete.hidden) || (aFCA.item_keywordfield.hidden && aFCA.item_selectall.hidden))
  628.         {
  629.             aFCA.sep_paste.hidden = true;
  630.         }
  631.         if (aFCA.p.pruning.searchselect)
  632.         {
  633.             aFCA.item_searchselect.hidden = true;
  634.         }
  635.         if (aFCA.p.pruning.frame)
  636.         {
  637.             aFCA.menu_frame.hidden = true;
  638.             aFCA.sep_frame.hidden = true;
  639.         }
  640.         if (aFCA.p.pruning.viewpartialsourceSelection)
  641.         {
  642.             aFCA.item_viewpartialsourceSelection.hidden = true;
  643.         }
  644.         if (aFCA.p.pruning.viewsource)
  645.         {
  646.             aFCA.item_viewsource.hidden = true;
  647.         }
  648.         if (aFCA.sep_viewsource && ((aFCA.item_viewsource.hidden && aFCA.item_viewinfo.hidden) || aFCA.item_savepage.hidden))
  649.         {
  650.             aFCA.sep_viewsource.hidden = true;
  651.         }
  652.         if (aFCA.p.pruning.spellCheck)
  653.         {
  654.             aFCA.item_spellCheck.hidden = true;
  655.             aFCA.sep_spell.hidden = true;
  656.         }
  657.         
  658.         //To-Remove
  659.         if (aFCA.item_metadata)
  660.         {
  661.             aFCA.item_metadata.hidden = true;
  662.         }
  663.         if (aFCA.sep_properties && (aFCA.item_viewpartialsourceSelection.hidden && aFCA.item_viewsource.hidden && aFCA.item_viewpartialsourceMathml.hidden && aFCA.item_viewinfo.hidden || aFCA.item_savepage.hidden))
  664.         {
  665.             aFCA.sep_properties.hidden = true;
  666.         }
  667.         
  668.         if (textWithin && aFCA.p.quick.bool)
  669.         {
  670.             aFCA.lastSelection = textWithin;
  671.  
  672.             if (textWithin.length > 20)
  673.             {
  674.                 textWithin = textWithin.substr(0, 20) + "ΓǪ";
  675.             }
  676.  
  677.             var label_quickMenu = aFCA.stringsBundle.getFormattedString("quickMenu.label", [textWithin]);
  678.             var accesskey_quickMenu = aFCA.stringsBundle.getString("quickMenu.accesskey");
  679.             
  680.             aFCA.menu_quick.label = label_quickMenu;
  681.             aFCA.menu_quick.setAttribute("accesskey", accesskey_quickMenu);
  682.             aFCA.menu_quick.hidden = false;
  683.             aFCA.sep_quick.hidden = false;
  684.             
  685.             if (aFCA.item_undo.hidden && aFCA.item_cut.hidden && aFCA.item_copy.hidden && aFCA.item_paste.hidden && aFCA.item_delete.hidden && aFCA.item_selectall && aFCA.item_spellCheck.hidden && aFCA.item_keywordfield.hidden)
  686.             {
  687.                 aFCA.sep_quick.hidden = true;
  688.             }
  689.             
  690.             var srcLang = aFCA.codeToLanguage(aFCA.p.quickW.srcLang);
  691.             var destLang = aFCA.codeToLanguage(aFCA.p.quickW.destLang);
  692.             
  693.             var label_googleTranslate = aFCA.stringsBundle.getString("googleTranslate.label");
  694.             var label_translateFrom =  aFCA.stringsBundle.getFormattedString("translateFrom.label", [srcLang]);
  695.             var label_translateTo = aFCA.stringsBundle.getFormattedString("translateTo.label", [destLang]);
  696.             
  697.             aFCA.item2_quick.label = label_googleTranslate;
  698.             aFCA.translateFrom.label = label_translateFrom;
  699.             aFCA.translateTo.label = label_translateTo;
  700.         }
  701.         else if (text && !gContextMenu.onLink && (!gContextMenu.isOnImage && aFCA.item_saveimage.hidden))
  702.         {
  703.             aFCA.lastSelection = text;
  704.             
  705.             if (aFCA.p.quick.menu || (aFCA.p.quick.bubble && (!doc.bubbleOk || !aFCA.translated || aFCA.isInBlacklist(doc.URL))))
  706.             {
  707.                 var label_googleTranslate = aFCA.stringsBundle.getString("googleTranslate.label");
  708.                 
  709.                 aFCA.item1_quick.label = label_googleTranslate;
  710.                 aFCA.item1_quick.hidden = false;
  711.                 aFCA.sep_quick.hidden = false;
  712.                 aFCA.translateText(text, aFCA.p.quick.srcLang, aFCA.p.quick.destLang, aFCA.updateItem1);
  713.             }
  714.             else if (doc.preview)
  715.             {
  716.                 aFCA.item1_quick.hidden = false;
  717.                 aFCA.sep_quick.hidden = false;
  718.             }
  719.             
  720.             if (text.length > 15)
  721.             {
  722.                 text = text.substr(0, 15) + "ΓǪ";
  723.             }
  724.             
  725.             if (aFCA.p.googleDictionary.bool)
  726.             {
  727.                 var label_googleDictionary = aFCA.stringsBundle.getFormattedString("googleDictionary.label", [text]);
  728.                 var accesskey_googleDictionary = aFCA.stringsBundle.getString("googleDictionary.accesskey");
  729.                 
  730.                 aFCA.item_googleDictionary.hidden = false;
  731.                 aFCA.item_googleDictionary.label = label_googleDictionary;
  732.                 aFCA.item_googleDictionary.setAttribute("accesskey", accesskey_googleDictionary);
  733.             }
  734.             
  735.             if (aFCA.p.customItem1.bool)
  736.             {
  737.                 var label_customItem1 = aFCA.stringsBundle.getFormattedString("customItemX.label", [aFCA.p.customItem1.name, text]);
  738.             
  739.                 aFCA.item_customItem1.hidden = false;
  740.                 aFCA.item_customItem1.label = label_customItem1;
  741.                 //aFCA.item_customItem1.setAttribute("accesskey", aFCA.p.customItem1.name[0]);
  742.             }
  743.             
  744.             if (aFCA.p.customItem2.bool)
  745.             {
  746.                 var label_customItem2 = aFCA.stringsBundle.getFormattedString("customItemX.label", [aFCA.p.customItem2.name, text]);
  747.                 
  748.                 aFCA.item_customItem2.hidden = false;
  749.                 aFCA.item_customItem2.label = label_customItem2;
  750.                 //aFCA.item_customItem2.setAttribute("accesskey", aFCA.p.customItem2.name[0]);
  751.             }
  752.             
  753.             if (aFCA.p.customItem3.bool)
  754.             {
  755.                 var label_customItem3 = aFCA.stringsBundle.getFormattedString("customItemX.label", [aFCA.p.customItem3.name, text]);
  756.             
  757.                 aFCA.item_customItem3.hidden = false;
  758.                 aFCA.item_customItem3.label = label_customItem3;
  759.                 //aFCA.item_customItem3.setAttribute("accesskey", aFCA.p.customItem3.name[0]);
  760.             }
  761.             
  762.             if ((aFCA.p.googleDictionary.bool || aFCA.p.customItem1.bool || aFCA.p.customItem2.bool || aFCA.p.customItem3.bool) && !(aFCA.item_copy.hidden && aFCA.item_selectall.hidden && aFCA.item_searchselect.hidden && aFCA.item_viewpartialsourceSelection.hidden))
  763.             {
  764.                 aFCA.sep_searchItems.hidden = false;
  765.             }
  766.         }
  767.         
  768.         if (gContextMenu.onLink && !gContextMenu.onMailtoLink)
  769.         {
  770.             if (aFCA.p.stuff.newChildTab)
  771.             {
  772.                 aFCA.item_newChildTab.hidden = false;
  773.                 
  774.                 if (!aFCA.p.pruning.openlink)
  775.                 {
  776.                     aFCA.sep_newChildTab.hidden = false;
  777.                 }
  778.             }
  779.         }
  780.         
  781.         if (!gContextMenu.onLink && !gContextMenu.isContentSelected && (!gContextMenu.isOnImage && aFCA.item_saveimage.hidden) && !gContextMenu.onTextInput)
  782.         {
  783.             var url = aFCA.getCurrentUrl();
  784.         
  785.             if (aFCA.p.stuff.bool && aFCA.ss.getTabValue(gBrowser.selectedTab, "ID"))
  786.             {
  787.                 aFCA.item_restoreChildTab.hidden = false;
  788.                 aFCA.sep_restoreChildTab.hidden = false;
  789.             }
  790.             
  791.             if (aFCA.p.stuff.bool && aFCA.ss.getTabValue(gBrowser.selectedTab, "parentTabID"))
  792.             {
  793.                 aFCA.item_closeThisChildTab.hidden = false;
  794.                 aFCA.sep_closeThisChildTab.hidden = false;
  795.             }
  796.             
  797.             if (aFCA.p.translateThisPage.bool && !url.match(/^https:\/\/|^http:\/\/translate\.google\.com|^http:\/\/www\.google\.com\/dictionary/))
  798.             {
  799.                 aFCA.item_translateThisPage.hidden = false;
  800.                 aFCA.sep_translateThisPage.hidden = false;
  801.             }
  802.             
  803.             if (aFCA.p.stuff.here || aFCA.p.quick.bubble || aFCA.p.stuff.middleClick)
  804.             {
  805.                 if (aFCA.isInBlacklist(url))
  806.                 {
  807.                     var label_unblacklist = aFCA.stringsBundle.getFormattedString("unblacklist.label", [aFCA.urlToSite(url)]);
  808.                     var accesskey_unblacklist = aFCA.stringsBundle.getString("unblacklist.accesskey");
  809.                 
  810.                     aFCA.item_blacklist.hidden = false;
  811.                     aFCA.item_blacklist.label = label_unblacklist;
  812.                     aFCA.item_blacklist.setAttribute("accesskey", accesskey_unblacklist);
  813.                     aFCA.sep_blacklist.hidden = false;
  814.                 }
  815.                 else
  816.                 {
  817.                     var label_blacklist = aFCA.stringsBundle.getFormattedString("blacklist.label", [aFCA.urlToSite(url)]);
  818.                     var accesskey_blacklist = aFCA.stringsBundle.getString("blacklist.accesskey");
  819.                 
  820.                     aFCA.item_blacklist.hidden = false;
  821.                     aFCA.item_blacklist.label = label_blacklist;
  822.                     aFCA.item_blacklist.setAttribute("accesskey", accesskey_blacklist);
  823.                     aFCA.sep_blacklist.hidden = false;
  824.                 }
  825.             }
  826.         }
  827.     },
  828.     
  829.     
  830.     p:
  831.     {
  832.         googleDictionary: {},
  833.         translateThisPage: {},
  834.         customItem1: {},
  835.         customItem2: {},
  836.         customItem3: {},
  837.         quick: {},
  838.         stuff: {},
  839.         pruning: {},
  840.         bubble: {},
  841.         quickW: {}
  842.     },
  843.     
  844.     
  845.     translateThisPage: function ()
  846.     {
  847.         if (aFCA.p.translateThisPage.inNewChildTab)
  848.         {
  849.             aFCA.openItem("translateThisPage");
  850.         }
  851.         else
  852.         {
  853.             var url = aFCA.getUrl("translateThisPage");
  854.             
  855.             loadURI(url);
  856.         }
  857.     },
  858.     
  859.     
  860.     getPrefs: function ()
  861.     {
  862.         aFCA.p.locale = aFCA.prefsGeneral.getCharPref("useragent.locale");
  863.         
  864.         aFCA.p.autoConfig = aFCA.prefsAfca.getBoolPref("autoConfig");
  865.         
  866.         aFCA.p.blacklist = aFCA.prefsAfca.getCharPref("blacklist");
  867.         
  868.         aFCA.p.googleDictionary.bool = aFCA.prefsAfca.getBoolPref("googleDictionary.bool");
  869.         aFCA.p.googleDictionary.langpair = aFCA.prefsAfca.getCharPref("googleDictionary.langpair");
  870.         aFCA.p.googleDictionary.lang = aFCA.prefsAfca.getCharPref("googleDictionary.lang");
  871.         aFCA.p.googleDictionary.bi = aFCA.prefsAfca.getBoolPref("googleDictionary.bi") && aFCA.p.googleDictionary.bool;
  872.         aFCA.p.googleDictionary.mono = !aFCA.p.googleDictionary.bi && aFCA.p.googleDictionary.bool;
  873.         
  874.         aFCA.p.translateThisPage.bool = aFCA.prefsAfca.getBoolPref("translateThisPage.bool");
  875.         aFCA.p.translateThisPage.destLang = aFCA.prefsAfca.getCharPref("translateThisPage.destLang");
  876.         aFCA.p.translateThisPage.inNewChildTab = aFCA.prefsAfca.getBoolPref("translateThisPage.inNewChildTab");
  877.         
  878.         aFCA.p.customItem1.bool = aFCA.prefsAfca.getBoolPref("customItem1.bool");
  879.         aFCA.p.customItem1.name = aFCA.prefsAfca.getCharPref("customItem1.name");
  880.         aFCA.p.customItem1.url = aFCA.prefsAfca.getCharPref("customItem1.url");
  881.         
  882.         aFCA.p.customItem2.bool = aFCA.prefsAfca.getBoolPref("customItem2.bool");
  883.         aFCA.p.customItem2.name = aFCA.prefsAfca.getCharPref("customItem2.name");
  884.         aFCA.p.customItem2.url = aFCA.prefsAfca.getCharPref("customItem2.url");
  885.         
  886.         aFCA.p.customItem3.bool = aFCA.prefsAfca.getBoolPref("customItem3.bool");
  887.         aFCA.p.customItem3.name = aFCA.prefsAfca.getCharPref("customItem3.name");
  888.         aFCA.p.customItem3.url = aFCA.prefsAfca.getCharPref("customItem3.url");
  889.         
  890.         aFCA.p.quick.srcLang = aFCA.prefsAfca.getCharPref("quick.srcLang");
  891.         aFCA.p.quick.destLang = aFCA.prefsAfca.getCharPref("quick.destLang");
  892.         aFCA.p.quick.bool = aFCA.prefsAfca.getBoolPref("quick.bool");
  893.         aFCA.p.quick.bMax = aFCA.prefsAfca.getIntPref("quick.bMax");
  894.         aFCA.p.quick.mMax = aFCA.prefsAfca.getIntPref("quick.mMax");
  895.         aFCA.p.quick.bubble = aFCA.prefsAfca.getBoolPref("quick.bubble") && aFCA.p.quick.bool;
  896.         aFCA.p.quick.menu = !aFCA.p.quick.bubble && aFCA.p.quick.bool;
  897.         
  898.         aFCA.p.stuff.bool = aFCA.prefsAfca.getBoolPref("stuff.bool");
  899.         aFCA.p.stuff.middleClick = aFCA.prefsAfca.getBoolPref("stuff.middleClick") && aFCA.p.stuff.bool;
  900.         aFCA.p.stuff.dx = aFCA.prefsAfca.getIntPref("stuff.dx");
  901.         aFCA.p.stuff.dy = aFCA.prefsAfca.getIntPref("stuff.dy");
  902.         aFCA.p.stuff.newChildTab = aFCA.prefsAfca.getBoolPref("stuff.newChildTab") && aFCA.p.stuff.bool;
  903.         aFCA.p.stuff.here = aFCA.prefsAfca.getBoolPref("stuff.here") && aFCA.p.stuff.bool;
  904.         aFCA.p.stuff.unselect = aFCA.prefsAfca.getBoolPref("stuff.here.unselect");
  905.         
  906.         aFCA.p.pruning.openlink = aFCA.prefsAfca.getBoolPref("pruning.context-openlink");
  907.         aFCA.p.pruning.bookmarklink = aFCA.prefsAfca.getBoolPref("pruning.context-bookmarklink");
  908.         aFCA.p.pruning.sendlink = aFCA.prefsAfca.getBoolPref("pruning.context-sendlink");
  909.         aFCA.p.pruning.sendimage = aFCA.prefsAfca.getBoolPref("pruning.context-sendimage");
  910.         aFCA.p.pruning.setDesktopBackground = aFCA.prefsAfca.getBoolPref("pruning.context-setDesktopBackground");
  911.         aFCA.p.pruning.blockimage = aFCA.prefsAfca.getBoolPref("pruning.context-blockimage");
  912.         aFCA.p.pruning.sendvideo = aFCA.prefsAfca.getBoolPref("pruning.context-sendvideo");
  913.         aFCA.p.pruning.sendaudio = aFCA.prefsAfca.getBoolPref("pruning.context-sendaudio");
  914.         aFCA.p.pruning.back = aFCA.prefsAfca.getBoolPref("pruning.context-back");
  915.         aFCA.p.pruning.forward = aFCA.prefsAfca.getBoolPref("pruning.context-forward");
  916.         aFCA.p.pruning.reload = aFCA.prefsAfca.getBoolPref("pruning.context-reload");
  917.         aFCA.p.pruning.stop = aFCA.prefsAfca.getBoolPref("pruning.context-stop");
  918.         aFCA.p.pruning.bookmarkpage = aFCA.prefsAfca.getBoolPref("pruning.context-bookmarkpage");
  919.         aFCA.p.pruning.savepage = aFCA.prefsAfca.getBoolPref("pruning.context-savepage");
  920.         aFCA.p.pruning.sendpage = aFCA.prefsAfca.getBoolPref("pruning.context-sendpage");
  921.         aFCA.p.pruning.viewbgimage = aFCA.prefsAfca.getBoolPref("pruning.context-viewbgimage");
  922.         aFCA.p.pruning.undo = aFCA.prefsAfca.getBoolPref("pruning.context-undo");
  923.         aFCA.p.pruning.cut = aFCA.prefsAfca.getBoolPref("pruning.context-cut");
  924.         aFCA.p.pruning.copy = aFCA.prefsAfca.getBoolPref("pruning.context-copy");
  925.         aFCA.p.pruning.paste = aFCA.prefsAfca.getBoolPref("pruning.context-paste");
  926.         aFCA.p.pruning.del = aFCA.prefsAfca.getBoolPref("pruning.context-delete");
  927.         aFCA.p.pruning.selectall = aFCA.prefsAfca.getBoolPref("pruning.context-selectall");
  928.         aFCA.p.pruning.searchselect = aFCA.prefsAfca.getBoolPref("pruning.context-searchselect");
  929.         aFCA.p.pruning.frame = aFCA.prefsAfca.getBoolPref("pruning.frame");
  930.         aFCA.p.pruning.viewpartialsourceSelection = aFCA.prefsAfca.getBoolPref("pruning.context-viewpartialsource-selection");
  931.         aFCA.p.pruning.viewsource = aFCA.prefsAfca.getBoolPref("pruning.context-viewsource");
  932.         aFCA.p.pruning.spellCheck = aFCA.prefsAfca.getBoolPref("pruning.spell-check-enabled");
  933.         
  934.         aFCA.p.bubble.background = aFCA.prefsAfca.getCharPref("bubble.background");
  935.         aFCA.p.bubble.fontSize = aFCA.prefsAfca.getCharPref("bubble.fontSize");
  936.         aFCA.p.bubble.fontWeight = aFCA.prefsAfca.getCharPref("bubble.fontWeight");
  937.         aFCA.p.bubble.fontFamily = aFCA.prefsAfca.getCharPref("bubble.fontFamily");
  938.         aFCA.p.bubble.fontColor = aFCA.prefsAfca.getCharPref("bubble.fontColor");
  939.         
  940.         aFCA.p.quickW.srcLang = aFCA.prefsAfca.getCharPref("quickW.srcLang");
  941.         aFCA.p.quickW.destLang = aFCA.prefsAfca.getCharPref("quickW.destLang");
  942.     },
  943.     
  944.     
  945.     observe: function (subject, topic, data)
  946.     {
  947.         if (topic != "nsPref:changed")
  948.         {
  949.             return;
  950.         }
  951.         
  952.         aFCA.getPrefs();
  953.         
  954.         var doc = content.document;
  955.         
  956.         switch (data)
  957.         {
  958.             case "quick.bool":
  959.             {
  960.                 aFCA.hideBubble();
  961.                 
  962.                 if (aFCA.p.quick.bubble)
  963.                 {
  964.                     aFCA.initBubble(doc);
  965.                 }
  966.                 break;
  967.             }
  968.             case "quick.bubble":
  969.             {
  970.                 aFCA.hideBubble();
  971.                 
  972.                 if (aFCA.p.quick.bubble)
  973.                 {
  974.                     aFCA.initBubble(doc);
  975.                 }
  976.                 break;
  977.             }
  978.             case "stuff.here":
  979.             {
  980.                 aFCA.hideHere();
  981.                 
  982.                 if (aFCA.p.stuff.here)
  983.                 {
  984.                     aFCA.initHere(doc);
  985.                 }
  986.                 break;
  987.             }
  988.             case "stuff.bool":
  989.             {
  990.                 aFCA.hideHere();
  991.                 aFCA.hideSkin();
  992.                 
  993.                 if (aFCA.p.stuff.here)
  994.                 {
  995.                     aFCA.initHere(doc);
  996.                 }
  997.                 
  998.                 if (!aFCA.p.stuff.middleClick)
  999.                 {
  1000.                     aFCA.prefsGeneral.setBoolPref("autoScroll", true);
  1001.                 }
  1002.                 else
  1003.                 {
  1004.                     aFCA.prefsGeneral.setBoolPref("autoScroll", false);
  1005.                 }
  1006.                 
  1007.                 break;
  1008.             }
  1009.             case "stuff.middleClick":
  1010.             {
  1011.                 aFCA.hideSkin();
  1012.                 
  1013.                 if (aFCA.ss.getTabValue(gBrowser.mTabs[gBrowser.getBrowserIndexForDocument(doc)], "parentTabID") && aFCA.p.stuff.middleClick)
  1014.                 {
  1015.                     aFCA.initSkin(doc);
  1016.                 }
  1017.                 
  1018.                 if (!aFCA.p.stuff.middleClick)
  1019.                 {
  1020.                     aFCA.prefsGeneral.setBoolPref("autoScroll", true);
  1021.                 }
  1022.                 else
  1023.                 {
  1024.                     aFCA.prefsGeneral.setBoolPref("autoScroll", false);
  1025.                 }
  1026.                 
  1027.                 break;
  1028.             }
  1029.             case "blacklist":
  1030.             {
  1031.                 aFCA.hideBubble();
  1032.                 aFCA.hideSkin();
  1033.                 aFCA.hideHere();
  1034.                 
  1035.                 if (aFCA.p.quick.bubble)
  1036.                 {
  1037.                     aFCA.initBubble(doc);
  1038.                 }
  1039.                 if (aFCA.ss.getTabValue(gBrowser.mTabs[gBrowser.getBrowserIndexForDocument(doc)], "parentTabID") && aFCA.p.stuff.middleClick)
  1040.                 {
  1041.                     aFCA.initSkin(doc);
  1042.                 }
  1043.                 if (aFCA.p.stuff.here)
  1044.                 {
  1045.                     aFCA.initHere(doc);
  1046.                 }
  1047.                 break;
  1048.             }
  1049.         }
  1050.     },
  1051.     
  1052.     
  1053.     blacklist: function ()
  1054.     {
  1055.         var url = aFCA.getCurrentUrl();
  1056.         var site = aFCA.urlToSite(url);
  1057.         var blacklist = aFCA.p.blacklist;
  1058.         
  1059.         if (blacklist.match(site))
  1060.         {
  1061.             blacklist = blacklist.replace(site + ", ", "");
  1062.             aFCA.prefsAfca.setCharPref("blacklist", blacklist);
  1063.         }
  1064.         else
  1065.         {
  1066.             blacklist = blacklist.replace(/,\s$/, ", " + site + ", ");
  1067.             aFCA.prefsAfca.setCharPref("blacklist", blacklist);
  1068.         }
  1069.     },
  1070.     
  1071.     
  1072.     isInBlacklist: function (url)
  1073.     {
  1074.         var site = aFCA.urlToSite(url);
  1075.         return aFCA.p.blacklist.match(site);
  1076.     },
  1077.     
  1078.     
  1079.     urlToSite: function (url)
  1080.     {
  1081.         return url.replace(/^.+:\/\//, "").replace(/\/.+/, "").replace("/", "");
  1082.     },
  1083.     
  1084.     
  1085.     skinProp:
  1086.     {
  1087.         w:    11,
  1088.         h:    11,
  1089.         path:    "chrome://aFewClicksAway/skin/skin11.png"
  1090.     },
  1091.     
  1092.     
  1093.     initSkin: function (doc)
  1094.     {
  1095.         if (doc.skinOk || aFCA.isInBlacklist(doc.URL) || !doc.body)
  1096.         {
  1097.             return;
  1098.         }
  1099.         doc.skinOk = true;
  1100.         
  1101.         aFCA.injectStretch(doc);
  1102.         aFCA.injectSkin(doc);
  1103.         aFCA.addSkinEvents(doc);
  1104.     },
  1105.     
  1106.     
  1107.     addSkinEvents: function (doc)
  1108.     {
  1109.         doc.addEventListener("mousemove", function (e) {aFCA.lastMouseMove = e; aFCA.updateSkinDisplay(e);}, false);
  1110.         
  1111.         aFCA.addOnMouseDown(doc);
  1112.  
  1113.         function onMouseOut (e)
  1114.         {
  1115.             var p = aFCA.getMousePositionOnClient(e);
  1116.         
  1117.             if (p.x < 0 || p.y < 0)
  1118.             {
  1119.                 aFCA.hideSkin();
  1120.             }
  1121.         }
  1122.         doc.addEventListener("mouseout", function (e) {onMouseOut(e);}, true);
  1123.         //Obviously stopping event propagation in the capturing phase is impossible...
  1124.         
  1125.         var anchors = doc.getElementsByTagName("a");
  1126.         
  1127.         for (var x = 0; x < anchors.length; x++)
  1128.         {
  1129.             anchors[x].addEventListener("mouseover", function () {doc.skinHiddenBecauseAnchor = true;}, false);
  1130.             anchors[x].addEventListener("mouseout", function () {doc.skinHiddenBecauseAnchor = false;}, false);
  1131.         }
  1132.     },
  1133.     
  1134.     
  1135.     injectSkin: function (doc)
  1136.     {
  1137.         if (doc.getElementById("skin"))
  1138.         {
  1139.             return; 
  1140.         }
  1141.         
  1142.         var p = aFCA.skinProp;
  1143.         var skin = doc.createElement("div");
  1144.         
  1145.         skin.id = "skin";
  1146.         
  1147.         skin.style.position = "fixed";
  1148.         skin.style.display = "none";
  1149.         skin.style.left = "0px";
  1150.         skin.style.top = "0px";
  1151.         skin.style.width = p.w + "px";
  1152.         skin.style.height = p.h + "px";
  1153.         skin.style.background = "url(" + p.path + ")";
  1154.         skin.style.zIndex= "10000";
  1155.         
  1156.         doc.body.appendChild(skin);
  1157.     },
  1158.     
  1159.     
  1160.     hideSkin: function ()
  1161.     {
  1162.         var skin = content.document.getElementById("skin");
  1163.         
  1164.         if (skin)
  1165.         {
  1166.             skin.style.display = "none";
  1167.         }
  1168.     },
  1169.     
  1170.     
  1171.     updateSkinDisplay: function (e)
  1172.     {
  1173.         var doc = content.document;
  1174.         var m = aFCA.getMousePositionOnClient(e);
  1175.         var skin = doc.getElementById("skin");
  1176.         
  1177.         if (!skin)
  1178.         {
  1179.             return;
  1180.         }
  1181.  
  1182.         if (!doc.skinHiddenBecauseAnchor && !aFCA.isInBlacklist(doc.URL) && !gContextMenu && aFCA.p.stuff.middleClick)
  1183.         {
  1184.             skin.style.left = m.x + aFCA.p.stuff.dx + "px";
  1185.             skin.style.top = m.y + aFCA.p.stuff.dy + "px";
  1186.             
  1187.             skin.style.display = "block";
  1188.         }
  1189.         else
  1190.         {
  1191.             skin.style.display = "none";
  1192.         }
  1193.     },
  1194.     
  1195.     
  1196.     translateText: function (text, srcLang, destLang, callback)
  1197.     {
  1198.         if (text.length > 5000)
  1199.         {
  1200.             text = text.substr(0, 5000);
  1201.         }
  1202.         
  1203.         if (srcLang == "auto")
  1204.         {
  1205.             srcLang = "";
  1206.         }
  1207.         
  1208.         text = encodeURIComponent(text);
  1209.         
  1210.         var url = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=" + text + "&langpair=" + srcLang + "%7C" + destLang;
  1211.         var referer = "http://addons.mozilla.org/addon/13547";
  1212.  
  1213.         function handler ()
  1214.         {
  1215.             if (req.readyState == 4)
  1216.             {
  1217.                 var json = JSON.parse(req.responseText);
  1218.                 
  1219.                 if (!json)
  1220.                 {
  1221.                     return callback("OopsΓǪ");
  1222.                 }
  1223.                 
  1224.                 var translatedText = json.responseData.translatedText;
  1225.                 aFCA.lastTranslation = translatedText;
  1226.                 
  1227.                 if (!srcLang)
  1228.                 {
  1229.                     var detectedLanguage = json.responseData.detectedSourceLanguage;
  1230.                 }
  1231.                 else
  1232.                 {
  1233.                     var detectedLanguage = "";
  1234.                 }
  1235.                 
  1236.                 return callback(translatedText, detectedLanguage);
  1237.             }
  1238.         }
  1239.         
  1240.         var req = new XMLHttpRequest();
  1241.         
  1242.         req.onreadystatechange = handler;
  1243.         req.open("GET", url);
  1244.         req.setRequestHeader("Referer", referer);
  1245.         req.send();
  1246.     },
  1247.     
  1248.     
  1249.     detectLanguage: function (text, callback)
  1250.     {
  1251.         if (text.length > 100)
  1252.         {
  1253.             text = text.substr(0, 100);
  1254.         }
  1255.         
  1256.         text = encodeURIComponent(text);
  1257.         
  1258.         var url = "http://ajax.googleapis.com/ajax/services/language/detect?v=1.0&q=" + text;
  1259.         var referer = "http://addons.mozilla.org/addon/13547";
  1260.  
  1261.         function handler ()
  1262.         {
  1263.             if (req.readyState == 4)
  1264.             {
  1265.                 var json = JSON.parse(req.responseText);
  1266.                 
  1267.                 if (!json)
  1268.                 {
  1269.                     return callback("OopsΓǪ");
  1270.                 }
  1271.                 
  1272.                 var language = json.responseData.language;
  1273.                 
  1274.                 return callback(language);
  1275.             }
  1276.         }
  1277.         
  1278.         var req = new XMLHttpRequest();
  1279.         
  1280.         req.onreadystatechange = handler;
  1281.         req.open("GET", url);
  1282.         req.setRequestHeader("Referer", referer);
  1283.         req.send();
  1284.     },
  1285.     
  1286.     
  1287.     isTranslatable: function (text)
  1288.     {
  1289.         return (text && !((!text.match(" ") && text.match(/\w\.\w|\d/))) && !text.match(/@|#|{|}|<|>|_|\+/));
  1290.     },
  1291.     
  1292.     
  1293.     displayBubble: function (translation, detectedLanguage)
  1294.     {
  1295.         aFCA.translated = true;
  1296.         
  1297.         var destLang = aFCA.p.quick.destLang;
  1298.         var doc = content.document;
  1299.         var bubble = doc.getElementById("bubble-div");
  1300.         var n = aFCA.p.quick.bMax;
  1301.         
  1302.         if (detectedLanguage == destLang || !aFCA.getSelectedText() || aFCA.isInBlacklist(doc.URL) || !bubble)
  1303.         {
  1304.             return;
  1305.         }
  1306.         
  1307.         if (translation.length > n)
  1308.         {
  1309.             doc.preview = true;
  1310.             aFCA.updateItem1(translation);
  1311.             translation = translation.substr(0, n) + "ΓǪ";
  1312.         }
  1313.         
  1314.         var ed = aFCA.lastMouseDown;
  1315.         var eu = aFCA.lastMouseUp;
  1316.         var ppd = aFCA.getMousePositionOnPage(ed);
  1317.         var pcd = aFCA.getMousePositionOnClient(ed);
  1318.         var ppu = aFCA.getMousePositionOnPage(eu);
  1319.         var pcu = aFCA.getMousePositionOnClient(eu);
  1320.         
  1321.         if (ppd.x - ppu.x < 0)
  1322.         {
  1323.             var ppx = ppd;
  1324.             var pcx = pcd;
  1325.         }
  1326.         else
  1327.         {
  1328.             var ppx = ppu;
  1329.             var pcx = pcu;
  1330.         }
  1331.         
  1332.         if (ppd.y - ppu.y < 0)
  1333.         {
  1334.             var ppy = ppd;
  1335.             var pcy = pcd;
  1336.         }
  1337.         else
  1338.         {
  1339.             var ppy = ppu;
  1340.             var pcy = pcu;
  1341.         }
  1342.         
  1343.         var fontSize = parseInt(bubble.style.fontSize);
  1344.         var height = 32 + fontSize;
  1345.         
  1346.         if (pcy.y - height < 0)
  1347.         {
  1348.             bubble.style.top = ppy.y + 17 + "px";
  1349.         }
  1350.         else
  1351.         {
  1352.             bubble.style.top = ppy.y - height + "px";
  1353.         }
  1354.         
  1355.         if (ppd.y == ppu.y && ppd.x == ppu.x)
  1356.         {
  1357.             bubble.style.left = ppx.x - 20 + "px";
  1358.         }
  1359.         else
  1360.         {
  1361.             bubble.style.left = ppx.x - 10 + "px";
  1362.         }
  1363.         
  1364.         bubble.innerHTML = translation;
  1365.         bubble.style.display = "block";
  1366.         
  1367.         var divHeight = bubble.offsetHeight;
  1368.         var lineHeight = bubble.style.lineHeight * parseInt(bubble.style.fontSize);
  1369.         var padding = parseInt(bubble.style.padding);
  1370.         
  1371.         var lines = Math.floor((divHeight - 2*padding) / lineHeight);
  1372.         
  1373.         if (lines != 1)
  1374.         {
  1375.             bubble.style.left = "10px";
  1376.             
  1377.             var w = doc.getElementsByTagName("html")[0].clientWidth;
  1378.             var divWidth = bubble.offsetWidth;
  1379.             
  1380.             bubble.style.left = w - divWidth -10 + "px";
  1381.         }
  1382.     },
  1383.     
  1384.     
  1385.     updateItem1: function (translation, detectedLanguage)
  1386.     {
  1387.         translation = aFCA.processText(translation);
  1388.         
  1389.         var n = aFCA.p.quick.mMax;
  1390.         
  1391.         if (translation.length > n)
  1392.         {
  1393.             translation = translation.substr(0, n) + "ΓǪ";
  1394.         }
  1395.  
  1396.         aFCA.item1_quick.label = translation;
  1397.     },
  1398.     
  1399.     
  1400.     updateItem2: function (translation, detectedLanguage)
  1401.     {
  1402.         translation = aFCA.processText(translation);
  1403.         
  1404.         var n = aFCA.p.quick.mMax;
  1405.         
  1406.         if (translation.length > n)
  1407.         {
  1408.             translation = translation.substr(0, n) + "ΓǪ";
  1409.         }
  1410.  
  1411.         aFCA.item2_quick.label = translation;
  1412.     },
  1413.     
  1414.     
  1415.     processText: function (text)
  1416.     {
  1417.         return text.replace(/'/g, "'")
  1418.                    .replace(/"/g, '"')
  1419.                    .replace(/\.\.\./g, "ΓǪ");
  1420.     },
  1421.  
  1422.     
  1423.     addOnMouseDown: function (doc)
  1424.     {
  1425.         if (doc.onMouseDownAdded || !doc.body)
  1426.         {
  1427.             return;
  1428.         }
  1429.         doc.onMouseDownAdded = true;
  1430.         
  1431.         function onMouseDown (e)
  1432.         {
  1433.             if (e.button == 0)
  1434.             {
  1435.                 aFCA.textOnMouseDown = aFCA.getSelectedText();
  1436.                 aFCA.lastMouseDown = e;
  1437.                 
  1438.                 aFCA.hideHere();
  1439.                 
  1440.                 if (!doc.holdOn)
  1441.                 {
  1442.                     aFCA.hideBubble();
  1443.                 }
  1444.                 
  1445.                 doc.preview = false;
  1446.             }
  1447.             
  1448.             if (e.button == 2)
  1449.             {
  1450.                 aFCA.lastRightClick = e;
  1451.             }
  1452.             
  1453.             var skin = doc.getElementById("skin");
  1454.             
  1455.             if (e.button == 0 || e.button == 1)
  1456.             {
  1457.                 if (skin)
  1458.                 {
  1459.                     aFCA.updateSkinDisplay(e);
  1460.                 }
  1461.             }
  1462.             
  1463.             if (e.button == 1 && skin && skin.style.display == "block")
  1464.             {
  1465.                 aFCA.closeAndGo("click");
  1466.             }
  1467.         }
  1468.         doc.addEventListener("mousedown", function (e) {onMouseDown(e);}, false);
  1469.     },
  1470.     
  1471.     
  1472.     addOnMouseUp: function (doc)
  1473.     {
  1474.         if (doc.onMouseUpAdded || !doc.body)
  1475.         {
  1476.             return;
  1477.         }
  1478.         doc.onMouseUpAdded = true;
  1479.         
  1480.         function onMouseUp (e)
  1481.         {
  1482.             if (e.button == 0)
  1483.             {
  1484.                 aFCA.lastMouseUp = e;
  1485.  
  1486.                 var ed = aFCA.lastMouseDown;
  1487.                 var eu = aFCA.lastMouseUp;
  1488.                 var ppd = aFCA.getMousePositionOnPage(ed);
  1489.                 var ppu = aFCA.getMousePositionOnPage(eu);
  1490.         
  1491.                 if (ppd.y == ppu.y && ppd.x == ppu.x && aFCA.textOnMouseDown)
  1492.                 {
  1493.                     return;
  1494.                 }
  1495.                 
  1496.                 var text = aFCA.getSelectedText();
  1497.                 
  1498.                 if (aFCA.p.quick.bubble && aFCA.isTranslatable(text) && !doc.holdOn)
  1499.                 {
  1500.                     aFCA.hideBubble();
  1501.                     aFCA.translated = false;
  1502.                     aFCA.translateText(text, aFCA.p.quick.srcLang, aFCA.p.quick.destLang, aFCA.displayBubble);
  1503.                 }
  1504.                 
  1505.                 if (text && !doc.holdOn)
  1506.                 {
  1507.                     aFCA.lastSelectionEvent = aFCA.lastMouseDown;
  1508.                 }
  1509.             }
  1510.         }
  1511.         doc.addEventListener("mouseup", function (e) {onMouseUp(e);}, false);
  1512.     },
  1513.     
  1514.     
  1515.     hideBubble: function ()
  1516.     {
  1517.         var bubble = content.document.getElementById("bubble-div");
  1518.         
  1519.         if (bubble)
  1520.         {
  1521.             bubble.style.display = "none";
  1522.         }
  1523.     },
  1524.     
  1525.     
  1526.     initBubble: function (doc)
  1527.     {
  1528.         if (doc.bubbleOk || aFCA.isInBlacklist(doc.URL) || !doc.body)
  1529.         {
  1530.             return;
  1531.         }
  1532.         doc.bubbleOk = true;
  1533.         
  1534.         aFCA.injectStretch(doc);
  1535.         aFCA.injectBubble(doc);
  1536.         aFCA.addOnMouseDown(doc);
  1537.         aFCA.addOnMouseUp(doc);
  1538.     },
  1539.     
  1540.     
  1541.     injectBubble: function (doc)
  1542.     {
  1543.         if (doc.getElementById("bubble-div"))
  1544.         {
  1545.             return;
  1546.         }
  1547.         
  1548.         var bubble = doc.createElement("div");
  1549.  
  1550.         bubble.id = "bubble-div";
  1551.         
  1552.         bubble.style.position = "absolute";
  1553.         bubble.style.display = "none";
  1554.         bubble.style.left = "0px";
  1555.         bubble.style.top = "0px";
  1556.         bubble.style.zIndex = "10000";
  1557.         bubble.style.width = "auto";
  1558.         bubble.style.heigth = "auto";
  1559.         bubble.style.padding = "6px";
  1560.         bubble.style.border = "thin solid grey";
  1561.         bubble.style.background = aFCA.p.bubble.background;
  1562.         bubble.style.color = aFCA.p.bubble.fontColor;
  1563.         bubble.style.marginRight = "9px";
  1564.         bubble.style.lineHeight = "1";
  1565.         bubble.style.fontSize = aFCA.p.bubble.fontSize;
  1566.         bubble.style.fontWeight = aFCA.p.bubble.fontWeight;
  1567.         bubble.style.fontFamily = aFCA.p.bubble.fontFamily;
  1568.         
  1569.         doc.body.appendChild(bubble);
  1570.         
  1571.         aFCA.injectStyle(doc, "div#bubble-div{-moz-border-radius: 5px; -moz-box-shadow: black 3px 3px 6px;}", "bubble-style");
  1572.         
  1573.         bubble.addEventListener("mouseover", function () {doc.holdOn = true;}, false);
  1574.         bubble.addEventListener("mouseout", function () {doc.holdOn = false;}, false);
  1575.     },
  1576.     
  1577.     
  1578.     getMousePositionOnPage: function (e)
  1579.     {
  1580.         var position =
  1581.         {
  1582.             x: e.pageX,
  1583.             y: e.pageY
  1584.         }
  1585.         return position;
  1586.     },
  1587.     
  1588.     
  1589.     getMousePositionOnClient: function (e)
  1590.     {
  1591.         var position =
  1592.         {
  1593.             x: e.clientX,
  1594.             y: e.clientY
  1595.         }
  1596.         return position;
  1597.     },
  1598.     
  1599.     
  1600.     injectStyle: function (doc, css, id)
  1601.     {
  1602.         if (doc.getElementById(id) || !doc.body)
  1603.         {
  1604.             return;
  1605.         }
  1606.         
  1607.         var style = doc.createElement("style");
  1608.         style.type = "text/css";
  1609.         style.innerHTML = css;
  1610.         style.id = id;
  1611.         doc.body.appendChild(style);
  1612.     },
  1613.     
  1614.     
  1615.     initHere: function (doc)
  1616.     {
  1617.         if (doc.hereOk || aFCA.isInBlacklist(doc.URL) || !doc.body)
  1618.         {
  1619.             return;
  1620.         }
  1621.         doc.hereOk = true;
  1622.         
  1623.         aFCA.injectStretch(doc);
  1624.         aFCA.injectHere(doc);
  1625.         aFCA.addOnMouseDown(doc);
  1626.         aFCA.addOnMouseUp(doc);
  1627.     },
  1628.     
  1629.     
  1630.     hereProp:
  1631.     {
  1632.         w:    50,
  1633.         h:    32,
  1634.         path:    "chrome://aFewClicksAway/skin/red-dot-shadow.png"
  1635.     },
  1636.     
  1637.     
  1638.     injectHere: function (doc)
  1639.     {
  1640.         if (doc.getElementById("here"))
  1641.         {
  1642.             return; 
  1643.         }
  1644.         
  1645.         var p = aFCA.hereProp;
  1646.         var here = doc.createElement("div");
  1647.         
  1648.         here.id = "here";
  1649.         
  1650.         here.style.position = "absolute";
  1651.         here.style.display = "none";
  1652.         here.style.left = "0px";
  1653.         here.style.top = "0px";
  1654.         here.style.width = p.w + "px";
  1655.         here.style.height = p.h + "px";
  1656.         here.style.background = "url(" + p.path + ")";
  1657.         here.style.zIndex= "10000";
  1658.         
  1659.         doc.body.appendChild(here);
  1660.     },
  1661.     
  1662.     
  1663.     updateHereDisplay: function (e)
  1664.     {
  1665.         var doc = content.document;
  1666.         var here = doc.getElementById("here");
  1667.         
  1668.         if (!here || aFCA.isInBlacklist(doc.URL))
  1669.         {
  1670.             return;
  1671.         }
  1672.         
  1673.         var m = aFCA.getMousePositionOnPage(e);
  1674.         var p = aFCA.hereProp;
  1675.  
  1676.         here.style.left = m.x - p.w/2 + "px";
  1677.         here.style.top = m.y - p.h + "px";
  1678.         here.style.display = "block";
  1679.     },
  1680.     
  1681.     
  1682.     hideHere: function ()
  1683.     {
  1684.         var here = content.document.getElementById("here");
  1685.         
  1686.         if (here)
  1687.         {
  1688.             here.style.display = "none";
  1689.         }
  1690.     },
  1691.     
  1692.     
  1693.     codeToLanguage: function (code)
  1694.     {
  1695.         return aFCA.stringsBundle.getString("lang." + code);
  1696.     }
  1697. }
  1698.  
  1699. window.addEventListener("load", function () {aFCA.init();}, false);